package com.idrem.util;

import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.List;
import java.util.Locale;

import android.provider.SyncStateContract.Constants;
import android.text.Html;
import android.text.Spanned;

/**
 * String utilities
 */
public class StringUtil {

//    /** decimal formatter **/
//    private static final DecimalFormat DECIMAL_FORMATTER = new DecimalFormat(
//        Constants.DECIMAL_FORMAT);

    /** integer formatter **/
    private static final NumberFormat INTEGER_FORMATTER = NumberFormat
        .getIntegerInstance(Locale.US);

//    /**
//     * format String
//     * 
//     * @param argString String to be formatted
//     * @return formtted String
//     */
//    public static String format(final String argString) {
//        return format(argString, Constants.DECIMAL_FORMAT);
//    }

    /**
     * format double
     * 
     * @param argDouble double to be formatted
     * @return formtted String
     */
//    public static String format(final double argDouble) {
//        return DECIMAL_FORMATTER.format(argDouble);
//    }

    /**
     * @param argString String to be formatted
     * @param argFormat Format pattern
     * @return formatted string
     */
    public static String format(final String argString, final String argFormat) {
        DecimalFormat formatter = new DecimalFormat(argFormat);
        try {
            Number n = formatter.parse(argString);
            return formatter.format(n);
            
        } catch (final Exception ex) {
            return argString;
        }
    }

    /**
     * Parses a Double from the specified string
     * 
     * @param argString String to be formatted
     * @return double value of specified string
     */
//    public static Double parseDouble(final String argString) {
//        if (argString == null) {
//            return null;
//        }
//
//        try {
//            return Double.valueOf(argString);
//            
//        } catch (final Exception ex) {
//            try {
//                return new Double(DECIMAL_FORMATTER.parse(argString).doubleValue());
//            } catch (final Exception e1) {
//                return null;
//            }
//        }
//    }

    /**
     * Parses a double from the specified string
     * 
     * @param argString specified string
     * @param defaultValue default value if parse fails
     * @return double value of specified string
     */
//    public static double parseDouble(final String argString, final double defaultValue) {
//        Double d = parseDouble(argString);
//        if (d == null) {
//            return defaultValue;
//        } else {
//            return d.doubleValue();
//        }
//    }

    /**
     * Parses an Integer from the specified string
     * 
     * @param argString String to be converted to integer
     * @return integer value of specified string
     */
    public static Integer parseInt(final String argString) {
        if (argString == null) {
            return null;
        }

        try {
            return Integer.valueOf(argString);
        } catch (final Exception ex) {
            try {
                return new Integer(INTEGER_FORMATTER.parse(argString).intValue());
            } catch (final Exception e1) {
                return null;
            }
        }
    }

    /**
     * Parses an integer from the specified string
     * 
     * @param argString String to be converted to integer
     * @param defaultValue default value if parse fails
     * @return integer value of specified string
     */
    public static int parseInt(final String argString, final int defaultValue) {
        Integer i = parseInt(argString);
        
        if (i == null) {
            return defaultValue;
        } else {
            return i.intValue();
        }
    }

    /**
     * Parses a Float from the specified string
     * 
     * @param argString String to be converted to float
     * @return float value of specified string
     */
//    public static Float parseFloat(final String argString) {
//        if (argString == null) {
//            return null;
//        } try {
//            return Float.valueOf(argString);
//        } catch (final Exception ex) {
//            try {
//                return new Float(DECIMAL_FORMATTER.parse(argString).floatValue());
//            } catch (final Exception e1) {
//                return null;
//            }
//        }
//    }

    /**
     * Parses a float from the specified string
     * 
     * @param argString String to be converted to float
     * @param defaultValue default value if parse fails
     * @return float value of specified string
     */
//    public static float parseFloat(final String argString, final float defaultValue) {
//        Float f = parseFloat(argString);
//        
//        if (f == null) {
//            return defaultValue;
//        } else {
//            return f.floatValue();
//        }
//    }

    /**
     * add strings
     * 
     * @param args strings to add
     * @return string
     */
    public static String add(String... args) {
    	
        if (args == null) {
            return null;
        } else {
            StringBuilder builder = new StringBuilder();

            for (String s : args) {
                if (s != null) {
                    builder.append(s);
                }
            }

            return builder.toString();
        }
    }

    /**
     * add strings with jointer
     * 
     * @param list the list of strings to add
     * @param jointer the jointer between strings
     * @return string
     */
//    public static String add(List<String> list, String jointer) {
//        return add((String[]) list.toArray(new String[0]), jointer);
//    }

    /**
     * add strings with jointer
     * 
     * @param argStrings strings to add
     * @param jointer the jointer between strings
     * @return string
     */
//    public static String add(String[] argStrings, String jointer) {
//        if (argStrings == null) {
//            return null;
//        } else {
//            StringBuilder builder = new StringBuilder();
//
//            for (String s : argStrings) {
//                if (SystemUtil.hasValue(s)) {
//                    if (builder.length() > 0 && jointer != null) {
//                        builder.append(jointer);
//                    }
//                    builder.append(s);
//                }
//            }
//
//            return builder.toString();
//        }
//    }

    /**
     * get special characters from web service.
     * 
     * @param source data from web service.
     * @return string data support special characters.
     */
    public static String fromHtml(String source) {
        String result = "";
        
        if (null == source || "".equals(source)) {
            return result;
        }
        Spanned spanned = Html.fromHtml(source);
        if (null != spanned) {
            result = spanned.toString();
        }
        return result;
    }
    
    /**
     * Converts a value to a string.
     * If the value is null then the default value is returned.
     * 
     * @param value the value to convert
     * @param defValue default value which to return if value is null
     * @return returns a String representation of the value or null if value is null
     */
    public static String toString(Object value, String defValue) {
        return ((value!=null) ? value.toString() : defValue);
    }

    /**
     * Converts a value to a string.
     * If the value is null then null will be returned.
     * 
     * @param value the value to convert
     * @return returns a String representation of the value or null if value is null
     */
    public static String toString(Object value) {
        return toString(value, null);
    }

    /**
     * Converts an array of objects to a string.
     * 
     * @param array array of objects
     * @param defValue default value which to return if array is null
     * @return returns a String representation of the array or the defaultValue if array is null
     */
    public static String toString(Object[] array, String defValue) {
        String s = arrayToString(array, "/");
        return (s!=null ? s : defValue);
    }

    /**
     * Converts an array of objects to a string.
     * 
     * @param array array of objects
     * @return returns a String representation of the array or null if the array is null
     */
    public static String toString(Object[] array) {
        return toString(array, null);
    }

    /**
     * Converts a value to a string.
     * if the value is null an empty string is returned.
     * 
     * @param value the value to convert
     * @return returns a String representation of the Object or an empty stringif o is null
     */
    public static String valueOf(Object value) {
        return toString(value, "");
    }

    /**
     * Converts an objects to a string.
     * 
     * @param array array of objects
     * @return returns a String representation of the array or an empty String if the array is null
     */
    public static String valueOf(Object[] array) {
        return toString(array, "");
    }
    
    /**
     * Returns the preferred String if it is not empty
     * ot the alternative String otherwise.
     * 
     * @param preferred the preferred String
     * @param alternative the alternative String if the preferred String is not valid
     * @return the preferred String if it is not empty ot the alternative String otherwise 
     */
    public static String coalesce(String preferred, String alternative) {
        return isValid(preferred) ? preferred : alternative;        
    }

    /**
     * Returns null if the value supplied is null or an empty String. 
     * 
     * @param value the value to check
     * @return null if the value supplied is null or an empty String or the value as a string otherwise 
     */
    public static String nullIfEmpty(Object value) {
        if (value==null)
            return null;
        String strval = value.toString();
        return ((strval.length()==0) ? null : strval);   
    }

    /**
     * Converts an array of objects to a string.
     * 
     * @param array array of objects
     * @param separator the separator to put between the object strings
     * @return returns a String
     */
    public static String arrayToString(Object[] array, String separator) {
        if (array == null || array.length < 1)
            return null; // Empty
        if (array.length > 1) { // multi Column Key
            StringBuilder buf = new StringBuilder();
            for (int i = 0; i < array.length; i++) {
                if (i > 0)
                    buf.append(separator);
                buf.append(array[i]);
            }
            return buf.toString();
        }
        // Only one member
        return String.valueOf(array[0]);
    }
    
    /**
     * Checks if a string is empty
     * 
     * @param s the String to check
     * 
     * @return true if s is empty or <code>null</code>
     */
    public static boolean isEmpty(String s) {
        return s == null || s.trim().length() == 0;
    }
    
    /**
     * Checks if a string is not null or empty
     * 
     * @param s the string to validate
     * 
     * @return true if valid
     * 
     * @deprecated this has been renamed to isNotEmpty
     */
    @Deprecated
    public static boolean isValid(String s) {
        return s != null && s.trim().length() > 0;
    }
    
    /**
     * Checks if a string is not null or empty
     * 
     * @param s the string to validate
     * 
     * @return true if valid
     */
    public static boolean isNotEmpty(String s) {
        return s != null && s.trim().length() > 0;
    }
    
    /**
     * Validates a given string. If the string is empty then null is returned. 
     * Otherwise the trimmed string is returned.
     * 
     * @param s the string to validate
     * @return the string or null if s was empty.
     */
    public static String validate(String s) {
    	//Add by Joe 20120109 Start
    	String str = s;
    	//Add End
        if (str==null)
            return null;
        str = str.trim();
        if (str.length()==0)
            return null;
        return str;
    }
    
    /**
     * Replaces all occurences of find in source by replace.
     * 
     * @param source the original String.
     * @param find the String to be replaced
     * @param replace the replacement string
     * 
     * @return a new string with all occurances of <code>find</code> in <code>source</code> replaced by <code>replace</code>
     */
    public static String replace(String source, String find, String replace) {
    	//Add by Joe 20120109 Start
    	String rep = replace;
    	//Add End
        // Check params
        if (source == null || find == null || find.length()==0)
            return source;
        // Find the character
        int index = source.indexOf(find);
        if (index < 0)
            return source;
        if (rep==null)
            rep="";
        // replace and find again
        int len = find.length();
        return source.substring(0,index)
             + rep
             + replace(source.substring(index+len), find, rep); 
    }

    /**
     * Returns a String with all occurrences of <code>from</code> within <code>orig</code> replaced with <code>to</code>.
     * If <code>orig</code> contains no occurrences of <code>from</code>, or if <code>from</code> is equal to
     * <code>to</code>,<code>orig</code> itself is returned rather than a copy being made. If orig is <code>null</code>,
     * <code>null</code> is returned.
     * 
     * @param source the original String.
     * @param find the String to be replaced
     * @param replace the replacement string
     * 
     * @return a new string with all occurances of <code>find</code> in <code>source</code> replaced by <code>replace</code>
     */
    public static String replaceAll(String source, String find, String replace) {
    	//Add by Joe 20120109 Start
    	String rep = replace;
    	//Add End
        if (source == null)
            return null;
        if (find == null || "".equals(find)) {
            return source;
        }
        if (rep == null) {
            rep = "";
        }
        int fromLength = find.length();
        int start = source.indexOf(find);
        if (start == -1) {
        	return source;
        }

        boolean greaterLength = (rep.length() >= fromLength);

        StringBuilder buffer;
        // If the "to" parameter is longer than (or
        // as long as) "from", the final length will
        // be at least as large
        if (greaterLength) {
            if (find.equals(rep))
                return source;
            buffer = new StringBuilder(source.length());
        } else {
            buffer = new StringBuilder();
        }

        char[] origChars = source.toCharArray();

        int copyFrom = 0;
        while (start != -1) {
            buffer.append(origChars, copyFrom, start - copyFrom);
            buffer.append(rep);
            copyFrom = start + fromLength;
            start = source.indexOf(find, copyFrom);
        }
        buffer.append(origChars, copyFrom, origChars.length - copyFrom);

        return buffer.toString();
    }
}
